﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using DataAccess;
using System.ComponentModel;
using System.Windows.Controls;
using System.Windows;
using SPIWareMVVM.Views.Commands;

namespace SPIWareMVVM.ViewModels
{
    public class OperatorRunTime
    {
        public TimeSpan RunTime = new TimeSpan();
        public string OperatorName { get; set; }
        public OperatorRunTime(MachineProduction mp)
        {
            RunTime = (DateTime)mp.EndTime - (DateTime)mp.StartTime;
            OperatorName = mp.ApplicationUser != null ? mp.ApplicationUser.UserName : string.Empty;
        }
        public override string ToString()
        {
            return string.Format("( {0} ) {1}", OperatorName, RunTime);
        }
    }
    public class MachineRunTime
    {
        public TimeSpan RunTime = new TimeSpan();
        public string MachineNumber { get; set; }
        public MachineRunTime(MachineProduction mp)
        {
            RunTime = (DateTime)mp.EndTime - (DateTime)mp.StartTime;
            MachineNumber = mp.MachinePress != null ? mp.MachinePress.MachineNumber : string.Empty;
        }
        public override string ToString()
        {
            return string.Format("( {0} ) {1}", MachineNumber, RunTime);
        }
    }
    public class ProductionViewModel : BaseViewModel
    {
        public ListBox lb { get; set; }
        TimeSpan _totalRunTime { get; set; }
        public TimeSpan TotalRunTime { get { return _totalRunTime; } set { _totalRunTime = value; OnPropertyChanged("TotalRunTime"); } }

        //public void ResetRunTimeVariables() { RunTimeVariables = new ObservableCollection<MachineProduction>(); }
        public static ObservableCollection<MachineProduction> RunTimeVariables = new ObservableCollection<MachineProduction>();
        public TimeSpan GetTotalRunTime(MachineProduction mp)
        {
            if (mp != null)
            {
                TimeSpan results = new TimeSpan();
                if (!RunTimeVariables.Contains(mp) && mp.EndTime != null) RunTimeVariables.Add(mp);
                foreach (MachineProduction item in RunTimeVariables)
                {
                    if (item.EndTime != null)
                    {
                        if (((DateTime)item.EndTime).Date == ((DateTime)mp.EndTime).Date)
                            results += ((DateTime)item.EndTime) - ((DateTime)item.StartTime);
                    }
                }
                return results;
            }
            return ApplicationData.SetTotalRunTime();
        }
        public ObservableCollection<MachineRunTime> GetMachineRunTimes(MachineProduction mp)
        {
            if (mp != null)
            {
                ObservableCollection<MachineRunTime> list = new ObservableCollection<MachineRunTime>();
                foreach (MachineProduction mProd in RunTimeVariables)
                {
                    //filter out non-selected listbox rundates ???
                    bool found = false;
                    foreach (MachineRunTime mrt in list)
                    {
                        if (mrt.MachineNumber == (mProd.MachinePress != null ? mProd.MachinePress.MachineNumber : string.Empty))
                        {
                            mrt.RunTime += (DateTime)mProd.EndTime - (DateTime)mProd.StartTime;
                            found = true;
                            break;
                        }
                    }
                    if (!found) list.Add(new MachineRunTime(mProd));
                }
                return list;
            }
            return ApplicationData.SetMachineRunTimes();
        }
        public ObservableCollection<OperatorRunTime> GetOperatorRunTimes(MachineProduction mp)
        {
            if (mp != null)
            {
                ObservableCollection<OperatorRunTime> list = new ObservableCollection<OperatorRunTime>();
                foreach (MachineProduction mProd in RunTimeVariables)
                {
                    bool found = false;
                    foreach (OperatorRunTime ort in list)
                    {
                        if (ort.OperatorName == (mProd.ApplicationUser != null ? mProd.ApplicationUser.FirstName : string.Empty))
                        {
                            ort.RunTime += (DateTime)mProd.EndTime - (DateTime)mProd.StartTime;
                            found = true;
                            break;
                        }
                    }
                    if (!found) list.Add(new OperatorRunTime(mProd));
                }
                return list;
            }
            return ApplicationData.SetOperatorRunTimes();
        }

        MachineProduction _selectedRun { get; set; }
        public MachineProduction SelectedRun
        {
            get { return _selectedRun; }
            set
            {
                _selectedRun = value;
                TotalRunTime = new TimeSpan();
                if (lb != null)
                {
                    foreach (MachineProduction mp in lb.Items)
                        TotalRunTime += (DateTime)mp.EndTime - (DateTime)mp.StartTime;
                }
                OnPropertyChanged("TotalRunTime");
                OnPropertyChanged("SelectedRun");
            }
        }

        MachinePress _selectedMachine { get; set; }
        public MachinePress SelectedMachine
        {
            get { return _selectedMachine; }
            set { _selectedMachine = value; OnPropertyChanged("SelectedMachine"); }
        }

        DateTime _runDate { get; set; }
        public DateTime RunDate
        {
            get
            {
                if (_runDate == null) _runDate = DateTime.Now.Date;
                return _runDate;
            }
            set
            {
                _runDate = value.Date; OnPropertyChanged("RunDate");
                var Operators = (from p in ApplicationData.ocProduction
                                 where ((DateTime)p.EndTime).Date == _runDate
                                 orderby p.UserId
                                 select new { });
            }
        }

        List<DateTime> _runDates { get; set; }
        public List<DateTime> RunDates
        {
            get
            {
                if (_runDates == null) _runDates = ApplicationData.ocProduction
                    .OrderBy(d => ((DateTime)d.EndTime).Date)
                    .Select(r => ((DateTime)r.EndTime).Date).Distinct().ToList();
                return _runDates;
            }
        }

        List<ApplicationUser> Users
        {
            get
            {
                return ApplicationData.ApplicationUsers.ToList();
            }
        }
        List<ProductionUser> _productionUsers { get; set; }
        public ObservableCollection<ProductionUser> Operators
        {
            get
            {
                if (_productionUsers == null)
                {
                    _productionUsers = new List<ProductionUser>();
                    foreach (ApplicationUser user in Users) _productionUsers.Add(new ProductionUser(user));
                }
                return _productionUsers.OrderBy(l => l.LastName).OrderBy(f => f.FirstName).ToObservableCollection<ProductionUser>();
            }
        }

        ObservableCollection<MachinePress> _ocMachines { get; set; }
        public ObservableCollection<MachinePress> ocMachines
        {
            get
            {
                if (_ocMachines == null) _ocMachines = ApplicationData.ocMachinePresses;
                return _ocMachines;
            }
        }

        ObservableCollection<WorkOrder> _ocWorkOrders { get; set; }
        public ObservableCollection<WorkOrder> ocWorkOrders { get { return ResetWorkOrderList(); } }
        private ObservableCollection<WorkOrder> ResetWorkOrderList()
        {
            if (_ocWorkOrders == null) _ocWorkOrders = ApplicationData.ocWorkOrders;
            if (this.SelectedRun != null && this.SelectedRun.MachinePress != null)
                return _ocWorkOrders.Where(w => w.Part.PressSize == SelectedRun.MachinePress.PressSize)
                    .OrderBy(c => c.WorkOrderId).ToObservableCollection<WorkOrder>();
            return _ocWorkOrders;
        }

        public void SetRunDate(DateTime endDate)
        {
            foreach (ProductionUser user in Operators)
                user.SetRunDate(endDate);
        }

        public int GetTotalCount()//int endCount, int startCount, int partsPerShot, int startPartsInBox, int endPartsinBox)
        {
            if (SelectedRun != null)
                return ((SelectedRun.EndCount - SelectedRun.StartCount) * (int)SelectedRun.Part.PartsPerShot)
                    - SelectedRun.StartPartsInBox + SelectedRun.EndPartsInBox;
            return 0;
            //return ((endCount - startCount) * partsPerShot) - startPartsInBox + endPartsinBox;
        }
    }

    public class ProductionUser : ApplicationUser, INotifyPropertyChanged
    {
        public string LastName { get { return User != null ? User.LastName : string.Empty; } set { } }
        public string FirstName { get { return User != null ? User.FirstName : string.Empty; } set { } }
        public string UserName { get { return User != null ? User.UserName : string.Empty; } set { } }

        public ApplicationUser User { get; set; }
        public DateTime RunDate { get; private set; }
        public TimeSpan RunTime
        {
            get
            {
                List<MachineProduction> list = User.MachineProductions.Where(d => ((DateTime)d.EndTime).Date == RunDate.Date).ToList();
                return list.Aggregate(TimeSpan.Zero, (subtotal, t) => subtotal.Add((DateTime)t.EndTime - (DateTime)t.StartTime));
            }
        }

        public ProductionUser(ApplicationUser user)
        {
            User = user;
            RunDate = DateTime.Now.Date;
        }
        public void SetRunDate(DateTime endDate)
        {
            RunDate = endDate;
            OnPropertyChanged("RunTime");
            OnPropertyChanged("RunDate");
        }

        #region Propertychanged
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                var e = new PropertyChangedEventArgs(propertyName);
                handler(this, e);
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion

        public override string ToString()
        {
            //return string.Format("{0} {1}", User.UserName, RunTime);
            return string.Format("{0}", User.UserName);
        }
    }
}
